from datetime import datetime
import random
import re

from flask import make_response, jsonify, request, current_app, json
from flask import session

from info import constants, redis_store, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from . import passport_blu
from info.utils.captcha.captcha import captcha
from info.utils.response_code import RET


#功能描述: 退出用户
# 请求路径: /passport/logout
# 请求方式: POST
# 请求参数: 无
# 返回值: errno, errmsg
@passport_blu.route('/logout', methods=['POST'])
def logout():
    # 清空session
    # session.clear()
    session.pop('user_id', None)
    session.pop('mobile', None)
    session.pop('nick_name', None)
    session.pop('is_admin', None)

    # 返回响应
    return jsonify(errno=RET.OK, errmsg="退出成功")


# 功能描述
# 请求路径: /passport/login
# 请求方式: POST
# 请求参数: mobile,password
# 返回值: errno, errmsg
@passport_blu.route('/login', methods=['POST'])
def login():
    """
        思路分析:
        1.获取参数
        2.校验参数
        3.通过手机号获取用户对象
        4.判断用户对象是否存在
        5.判断密码是否正确
        6.保存用户的登陆信息到session ?
        7.返回响应
        """
    #1.获取参数
    mobile = request.json.get('mobile')
    password = request.json.get('password')

    #2.校验参数
    if not all([mobile, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    if not re.match('1[35789]\d{9}', mobile):
        return jsonify(errno=RET.DATAERR, errmsg='手机号格式有误')

    #3.通过手机号获取用户对象
    try:
        user = User.query.filter(User.mobile == mobile).first()
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='查询用户异常')

    #4.判断用户对象是否存在
    if not user:
        return jsonify(errno=RET.NODATA, errmsg='该用户未注册')

    #5.判断密码是否正确
    if not user.check_passowrd(password):
        return jsonify(errno=RET.DATAERR, errmsg='密码错误')

    #6.保存用户的登陆信息到session
    session['user_id'] = user.id
    session['mobile'] = user.mobile
    session['nick_name'] = user.nick_name
    session['is_admin'] = user.is_admin

    #用户最后登陆时间
    user.last_login = datetime.now()

    #7.返回响应
    return jsonify(errno=RET.OK, errmsg='登陆成功')



# 功能描述：注册用户
# 请求路径：/passport/register
# 请求方式: POST
# 请求参数: mobile, sms_code,password
# 返回值: errno, errmsg
@passport_blu.route('/register', methods=['POST'])
def register():
    """
        思路分析:
        1.获取参数
        2.校验参数,为空校验
        3.通过手机号取出短信验证码
        4.判断短信验证码是否过期
        5.删除redis短信验证码
        6.判断验证码正确性
        7.创建用户对象
        8.设置用户属性
        9.保存到数据库
        10.返回响应
        """
#1.获取参数
# json_data = request.data
# dict_data = json.loads(json_data)
#上面两句话可以写成request.get_json()或request.json
    dict_data = request.json
    mobile = dict_data.get('mobile')
    sms_code = dict_data.get('sms_code')
    password = dict_data.get('password')

    # 2.校验参数,为空校验
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    # 3.通过手机号取出短信验证码
    try:
        redis_sms_code = redis_store.get('sms_code:%s' % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取短信验证码异常')

    # 4.判断短信验证码是否过期
    if not redis_sms_code:
        return jsonify(errno=RET.NODATA, errmsg='短信验证码过期')

    # 5.删除redis短信验证码
    try:
        redis_store.delete('sms_code:%s' % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='删除短信验证码异常')

    # 6.判断验证码正确性
    if sms_code != redis_sms_code:
        return jsonify(errno=RET.DATAERR, errmsg='短信验证码错误')

    # 7.创建用户对象
    user = User()

    # 8.设置用户属性
    user.nick_name = mobile
    user.password = password
    user.mobile = mobile

    # 9.保存到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DBERR, errmsg='用户注册失败')

    # 10.返回响应
    return jsonify(errno=RET.OK, errmsg="注册成功")


#功能描述：发送短信
#请求地址：/passport/sms_code
#请求方式：POST
#请求参数：mobile, image_code, image_code_id
#返回值：errno, errmsg
@passport_blu.route('/sms_code', methods=['POST'])
def get_sms_code():
    """
        思路分析:
        1.获取参数
        2.校验参数,为空检验,格式校验
        3.取出redis中的图片验证码
        4.判断是否过期
        5.删除redis中图片验证码
        6.正确性判断
        7.生成短信验证码
        8.发送短信
        9.判断是否发送成功
        10.保存短信验证码到redis
        11.返回响应
        """
    json_data = request.data
    dict_data = json.loads(json_data)
    mobile = dict_data.get('mobile')
    image_code = dict_data.get('image_code')
    image_code_id = dict_data.get('image_code_id')

    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')
    if not re.match('1[3456789]\d{9}', mobile):
        return jsonify(errno=RET.DATAERR, errmsg='手机号格式不正确')

    try:
        redis_image_code = redis_store.get('image_code:%s' % image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='数据获取失败')
    if not redis_image_code:
        return jsonify(errno=RET.NODATA, errmsg='验证码过期')

    try:
        redis_store.delete('image_code:%s' % image_code_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='获取失败')

    if image_code.upper() != redis_image_code.upper():
        return jsonify(errno=RET.DATAERR, errmsg='图片验证码错误')

    sms_code = '%06d' % random.randint(0,999999)
    current_app.logger.debug('短信验证码 = %s' % sms_code)
    # try:
    #     ccp = CCP()
    #     result = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES / 60], 1)
    # except Exception as e:
    #     current_app.logger.error(e)
    #     return jsonify(errno=RET.THIRDERR, errmsg='云通讯发送失败')
    #
    # if result == -1:
    #     return jsonify(errno=RET.DATAERR, errmsg='短信发送失败')

    try:
        redis_store.set('sms_code:%s' % mobile, sms_code, constants.SMS_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg='短信保存失败')

    return jsonify(errno=RET.OK, errmsg='发送成功')

#功能描述：图片验证码
#请求地址：/passport/image_code
#请求方式：GET
#请求参数：随机字符串(uuid)cur_id,上一个字符串pre_id
#返回值：返回图片


@passport_blu.route('/image_code')
def get_image_code():
    """
        思路分析:
        1.获取参数
        2.校验参数
        3.生成图片验证码
        4.保存到redis
        5.返回
        """
    cur_id = request.args.get('cur_id')
    pre_id = request.args.get('pre_id')

    if not cur_id:
        return jsonify(errno=RET.PARAMERR, errmsg='参数不全')

    #3.生成图片验证码
    name, text, image_data = captcha.generate_captcha()
    # 4.保存到redis
    # 参数1:保存到redis的key
    # 参数2:图片验证码
    # 参数3:过期时间
    try:
        redis_store.set('image_code:%s' % cur_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
        if pre_id:
            redis_store.delete('image_code:%s' % pre_id)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(erroron=RET.DBERR, errmsg='验证操作失败')

    response = make_response(image_data)
    response.headers["Content-Type"] = 'image/jpg'
    return response